package com.vcar.LDiceClient.dataproxy
{
	import com.vcar.LDiceClient.config.Config;
	import com.vcar.LDiceClient.config.GlobalEventName;
	import com.vcar.LDiceClient.config.ModuleName;
	import com.vcar.LDiceClient.config.ProxyNames;
	import com.vcar.LDiceClient.core.HeartBeatTick;
	import com.vcar.LDiceClient.dataproxy.module.ModuleInfo;
	import com.vcar.LDiceClient.manager.TickManager;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	
	import mx.controls.Alert;
	
	import org.puremvc.as3.patterns.proxy.Proxy;

	/**
	 * socket代理
	 * @author rhj
	 *
	 */
	public class SocketProxy extends Proxy
	{
		private var _socket:Socket;
		private var bytes:ByteArray; //接收缓冲
		private var ispolicy:Boolean;
		/**
		 * onData应该是一个线程安全的函数
		 * funlock用于给函数加锁
		 */
		private var funlock:Boolean;

		/**
		 * 请求后的回调函数所集合，
		 * key requestid
		 * val {fun:callback,capture:false}
		 */
		private var callback:Dictionary;

		public function SocketProxy(data:Object=null)
		{
			var r1:ResponseMessage;

			super(ProxyNames.SocketProxy, data);
			bytes=new ByteArray();
			callback=new Dictionary();
		}

		public function connect():void
		{
			if (_socket == null || _socket.connected == false)
			{
				_socket=new Socket();
				_socket.addEventListener(Event.CONNECT, onConnect);
				_socket.addEventListener(Event.CLOSE, onClose);
				_socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
				_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onPolicyError);
				_socket.addEventListener(ProgressEvent.SOCKET_DATA, onData);
				_socket.connect(Config.chatHost,Config.chatPort);
			}
		}

		private function onConnect(event:Event):void
		{
			trace("建立连接成功");
		}

		private function onError(event:IOErrorEvent):void
		{
			Alert.show(event.text);
			trace(_socket.connected);
			_socket.close();
		}

		private function onClose(event:Event):void
		{
			Alert.show("与服务端的联接断开");
			TickManager.instance.removeTick(new HeartBeatTick());
			
			var m:ModuleInfo=new ModuleInfo(ModuleName.LOGIN_MODULE);
			sendNotification(GlobalEventName.MODULE_CHANGE,m);
			
			_socket.close();
			
		}

		private function onPolicyError(event:SecurityErrorEvent):void
		{
			Alert.show(event.text);
			_socket.close();
		}

		/**
		 * 接收数据
		 * @param event
		 *
		 */
		private function onData(event:ProgressEvent):void
		{
			if (funlock)
			{
				return;
			}
			funlock=true;
			var ba:ByteArray=new ByteArray();

			while (_socket.bytesAvailable)
			{
				_socket.readBytes(ba, 0, _socket.bytesAvailable);
			}

			if (!ispolicy) //第一次为策略数据
			{
				ispolicy=true;
				funlock=false;
				return;
			}

			bytes.writeBytes(ba);
			bytes.position=0;
			while (bytes.bytesAvailable >= 4)
			{
				bytes.readBytes(ba, 0, 4);
				var len:int=(ba[0] & 0xFF) + ((ba[1] & 0xFF) << 8) + ((ba[2] & 0xFF) << 16) + ((ba[3] & 0xFF) << 24);

				if (bytes.bytesAvailable + 4 >= len)
				{
					//bytes.readBytes(ba,0,len - 4);

					var obj:ResponseMessage=bytes.readObject() as ResponseMessage;
					if (callback[obj.requestId] != null)
					{
						if (callback[obj.requestId].cap)
						{
							(callback[obj.requestId].fun as Function).apply(null, [obj]);
						}
						else
						{
							(callback[obj.requestId].fun as Function).apply(null, [obj]);
							delete callback[obj.requestId];
							facade.sendNotification(GlobalEventName.SOCKET_DATA_RECV, obj);
						}
					}
					else
					{
						facade.sendNotification(GlobalEventName.SOCKET_DATA_RECV, obj);
					}

				}
				else
				{
					bytes.position=0; // 恢复
					break;
				}
			}

			//将已读取的object从数据中删除
			ba=new ByteArray();
			bytes.readBytes(ba);
			bytes=ba;
			ba=null;
			funlock=false;

		}

		/**
		 * flash向服务端发起一次请求
		 * @param obj 请求对像
		 * @param succFun 当次请求结果返回的处理函数
		 * @param capture 经过succFun处理后，是否向框架发送消息
		 *
		 */
		public function send(obj:RequestMessage, succFun:Function=null, capture:Boolean=false):void
		{
			connect();
			if (succFun != null)
			{
				callback[obj.requestId]={fun: succFun, cap: capture};
			}
			
			_socket.writeObject(obj);
			_socket.flush();
		}


	}
}